{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python中JSON操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 引入json模块\n",
    "import json\n",
    "import os"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 函数定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 文件保存函数1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def save_file(json_string, file_name, coding):\n",
    "    \"\"\"\n",
    "    保存文件函数：把字符串保存成文件\n",
    "    :param json_string:\n",
    "    :param file_name:\n",
    "    :param coding:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    with open(file_name, 'w', encoding=coding) as fp:\n",
    "        fp.write(json_string)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 文件保存函数2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def dump_save_file(json_string, file_name, coding):\n",
    "    \"\"\"\n",
    "    使用dump函数，保存文件\n",
    "    # json.dump(json_string, fp) 这样写会中文乱码，\n",
    "    # 如果要保存含有中文的字符串，建议加上ensure_ascii=False,json.dump默认使用ascii字符码\n",
    "\n",
    "    :param json_string: 要保存的json字符串\n",
    "    :param file_name: 要保存的文件名称\n",
    "    :param coding: 字符编码(如utf-8)\n",
    "    :return: 没有返回值\n",
    "    \"\"\"\n",
    "    with open(file_name, 'w', encoding=coding) as fp:\n",
    "        json.dump(json_string, fp, ensure_ascii=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 文件读取函数1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def read_json_file(file_name, coding):\n",
    "    \"\"\"\n",
    "    使用json.load读取json文件\n",
    "    :param file_name: 文件名\n",
    "    :param coding: 编码（如utf-8）\n",
    "    :return: <class 'list'>\n",
    "    \"\"\"\n",
    "    with open(file_name, 'r', encoding=coding) as fp:\n",
    "        persons = json.load(fp)\n",
    "    return persons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'country': 'china', 'username': '张三', 'age': 18}, {'country': 'china', 'username': '李四', 'age': 20}, {'country': 'china', 'username': '王五', 'age': 32}]\n"
     ]
    }
   ],
   "source": [
    "json_file =  read_json_file('./person1.json','utf-8')\n",
    "print(json_file)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 文件读取函数2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def read_file(file_name,coding):\n",
    "    with open(file_name, 'r',encoding=coding) as f:\n",
    "        content = f.read()\n",
    "    return content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{\"country\": \"china\", \"age\": 18, \"username\": \"张三\"}, {\"country\": \"china\", \"age\": 20, \"username\": \"李四\"}, {\"country\": \"china\", \"age\": 32, \"username\": \"王五\"}]\n"
     ]
    }
   ],
   "source": [
    "file = read_file('./person1.json','utf-8')\n",
    "print(file)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "python文件对象提供了三个“读”方法： read()、readline() 和 readlines()。每种方法可以接受一个变量以限制每次读取的数据量。  \n",
    "\n",
    "- read() 每次读取整个文件，它通常用于将文件内容放到一个字符串变量中。如果文件大于可用内存，为了保险起见，可以反复调用read(size)方法，每次最多读取size个字节的内容。   \n",
    "- readlines() 之间的差异是后者一次读取整个文件，象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表，该列表可以由 Python 的 for ... in ... 结构进行处理。  \n",
    "- readline() 每次只读取一行，通常比readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时，才应该使用 readline()。\n",
    "<b> 注意：这三种方法是把每行末尾的'\\n'也读进来了，它并不会默认的把'\\n'去掉，需要我们手动去掉。 </b>\n",
    "\n",
    "这三种方法是把每行末尾的'\\n'也读进来了，它并不会默认的把'\\n'去掉，需要我们手动去掉。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "with open('test1.txt', 'r') as f1:\n",
    "    list1 = f1.readlines()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['111\\n', '222\\n', '333\\n', '444\\n', '555']"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>######去掉n#####</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['111', '222', '333', '444', '555']"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "with open('test1.txt', 'r') as f1:\n",
    "    list1 = f1.readlines()\n",
    "for i in range(0, len(list1)):\n",
    "    list1[i] = list1[i].rstrip('\\n')\n",
    "    \n",
    "list1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# json.dumps使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 用于将把python对象(dict类型/list类型)的数据转成str(json格式的str)，  \n",
    " (1).因为如果直接将dict类型/list类型的数据写入json文件中会发生报错，因此在将数据写入时需要用到该函数;   \n",
    " (2).json.dumps会格式化python对象的代码，转换成jsons标准格式。 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 把python对象代码，转换成json格式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"age\": 20, \"score\": 88, \"name\": \"Bob\"}\n"
     ]
    }
   ],
   "source": [
    "d = dict(name='Bob', age=20, score=88)\n",
    "print(json.dumps(d))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"country\": \"china\", \"age\": 18, \"username\": \"zhangsan\"}\n"
     ]
    }
   ],
   "source": [
    "persons_dic = {'username': \"zhangsan\", 'age': 18, 'country': 'china'}\n",
    "print(json.dumps(persons_dic))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## python对象保存前使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "persons = [\n",
    "            {\n",
    "                'username': \"张三\",\n",
    "                'age': 18,\n",
    "                'country': 'china'\n",
    "            },\n",
    "            {\n",
    "                'username': '李四',\n",
    "                'age': 20,\n",
    "                'country': 'china'\n",
    "            },\n",
    "            {\n",
    "                'username': '王五',\n",
    "                'age': 32,\n",
    "                'country': 'china'\n",
    "            }\n",
    "        ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'>\n",
      "<class 'str'>\n"
     ]
    }
   ],
   "source": [
    "print(type(persons))\n",
    "print(type(json.dumps(persons)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### python对象直接保存会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "write() argument must be str, not list",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-67-a67914b79c9d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msave_file\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpersons\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'person.json'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'utf-8'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-25-37fc0e41a092>\u001b[0m in \u001b[0;36msave_file\u001b[0;34m(json_string, file_name, coding)\u001b[0m\n\u001b[1;32m      8\u001b[0m     \"\"\"\n\u001b[1;32m      9\u001b[0m     \u001b[1;32mwith\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfile_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'w'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mcoding\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mfp\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m         \u001b[0mfp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mjson_string\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: write() argument must be str, not list"
     ]
    }
   ],
   "source": [
    "save_file(persons, 'person.json', 'utf-8')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 先转换，后保存，不会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "成功移除文件：person.json\n",
      "person.json文件已生成...\n"
     ]
    }
   ],
   "source": [
    "# 定义文件名\n",
    "file_name = 'person.json'\n",
    "# 如果存在，先删除\n",
    "if os.path.exists(file_name):\n",
    "    os.remove(file_name)\n",
    "    print('成功移除文件：%s' % file_name)\n",
    "\n",
    "# 保存文件\n",
    "person_string = json.dumps(persons)\n",
    "save_file(person_string, file_name , 'utf-8')\n",
    "\n",
    "# 判断文件是否存在\n",
    "if os.path.exists(file_name):\n",
    "    print(\"person.json文件已生成...\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# json.dump()使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "json.dump()用于将Python内置类型序列化为json对象后写入文件 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def dump_save_file(json_string, file_name, coding):\n",
    "    \"\"\"\n",
    "    使用dump函数，保存文件\n",
    "    # json.dump(json_string, fp) 这样写会中文乱码，\n",
    "    # 如果要保存含有中文的字符串，建议加上ensure_ascii=False,json.dump默认使用ascii字符码\n",
    "\n",
    "    :param json_string: 要保存的json字符串\n",
    "    :param file_name: 要保存的文件名称\n",
    "    :param coding: 字符编码(如utf-8)\n",
    "    :return: 没有返回值\n",
    "    \"\"\"\n",
    "    with open(file_name, 'w', encoding=coding) as fp:\n",
    "        json.dump(json_string, fp, ensure_ascii=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用json.dump进行dict直接保存,不会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "成功移除文件：person1.json\n",
      "person1.json文件已生成...\n"
     ]
    }
   ],
   "source": [
    "# 定义文件名\n",
    "file_name = 'person1.json'\n",
    "# 如果存在，先删除\n",
    "if os.path.exists(file_name):\n",
    "    os.remove(file_name)\n",
    "    print('成功移除文件：%s' % file_name)\n",
    "\n",
    "# 保存文件\n",
    "dump_save_file(persons, file_name, 'utf-8')\n",
    "# 判断文件是否存在\n",
    "if os.path.exists(file_name):\n",
    "    print(\"person1.json文件已生成...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# json.loads 使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " json.loads()把Json格式(str)字符串解码转换成Python对象(dict/list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 把字典转为json格式的字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "print(type(persons))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{\"country\": \"china\", \"age\": 18, \"username\": \"\\u5f20\\u4e09\"}, {\"country\": \"china\", \"age\": 20, \"username\": \"\\u674e\\u56db\"}, {\"country\": \"china\", \"age\": 32, \"username\": \"\\u738b\\u4e94\"}]\n"
     ]
    }
   ],
   "source": [
    "# json.dumps 默认使用ascii编码\n",
    "persons_str = json.dumps(persons)\n",
    "print(persons_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{\"country\": \"china\", \"age\": 18, \"username\": \"张三\"}, {\"country\": \"china\", \"age\": 20, \"username\": \"李四\"}, {\"country\": \"china\", \"age\": 32, \"username\": \"王五\"}]\n"
     ]
    }
   ],
   "source": [
    "# 把ensure_ascii设为False中文不会乱\n",
    "persons_str = json.dumps(persons,ensure_ascii=False)\n",
    "print(persons_str)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 把字符串转化为字典"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "persons_dict = json.loads(persons_str)\n",
    "print(type(persons_dict))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "张三\n"
     ]
    }
   ],
   "source": [
    "print(persons_dict[0]['username'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'b': '2222', 'c': '3333', 'a': '1111', 'd': '4444'}\n",
      "**************************************************\n",
      "{\"b\": \"2222\", \"c\": \"3333\", \"a\": \"1111\", \"d\": \"4444\"}\n",
      "**************************************************\n",
      "{'b': '2222', 'a': '1111', 'c': '3333', 'd': '4444'}\n",
      "**************************************************\n",
      "<class 'dict'>\n",
      "<class 'str'>\n",
      "<class 'dict'>\n"
     ]
    }
   ],
   "source": [
    "name_emb = {'a':'1111','b':'2222','c':'3333','d':'4444'}\n",
    "# 把字典转为json格式的字符串\n",
    "jsDumps = json.dumps(name_emb)\n",
    "# 把字符串转化为字典\n",
    "jsLoads = json.loads(jsDumps)\n",
    " \n",
    "print(name_emb)\n",
    "print('*'*50)\n",
    "\n",
    "print(jsDumps)\n",
    "print('*'*50)\n",
    "\n",
    "print(jsLoads)\n",
    "print('*'*50)\n",
    " \n",
    "print(type(name_emb))\n",
    "print(type(jsDumps))\n",
    "print(type(jsLoads))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1111\n"
     ]
    }
   ],
   "source": [
    "print(jsLoads['a'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "string indices must be integers",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-44-4771df0b706a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mjsDumps\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: string indices must be integers"
     ]
    }
   ],
   "source": [
    "print(jsDumps['a'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# json.load() 使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "json.load()用于从json文件中读取数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def read_json_file(file_name, coding):\n",
    "    \"\"\"\n",
    "    使用json.load读取json文件\n",
    "    :param file_name: 文件名\n",
    "    :param coding: 编码（如utf-8）\n",
    "    :return: <class 'list'>\n",
    "    \"\"\"\n",
    "    with open(file_name, 'r', encoding=coding) as fp:\n",
    "        persons = json.load(fp)\n",
    "    return persons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'>\n",
      "[{'country': 'china', 'age': 18, 'username': '张三'}, {'country': 'china', 'age': 20, 'username': '李四'}, {'country': 'china', 'age': 32, 'username': '王五'}]\n"
     ]
    }
   ],
   "source": [
    "person_list = read_json_file('person1.json', 'utf-8')\n",
    "print(type(person_list))\n",
    "print(person_list)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'>\n",
      "[{'country': 'china', 'age': 18, 'username': '张三'}, {'country': 'china', 'age': 20, 'username': '李四'}, {'country': 'china', 'age': 32, 'username': '王五'}]\n"
     ]
    }
   ],
   "source": [
    "person_list1 = read_json_file('person1.json', 'utf-8')\n",
    "print(type(person_list1))\n",
    "print(person_list1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "273px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
